#include "TWI.h"
#include <string.h>

void TWI_Init(char twie)
{
    //TWI initialize
    // bit rate:20
    TWCR= 0X00; //disable twi
    TWBR= 0x14; //set bit rate
    TWSR= 0x03; //set prescale
    TWAR= 0x01; //set slave address
    TWCR= 0x44 | twie; //enable twi
}

unsigned char TWI_SendCharTo(unsigned char address, char ch)
{
    unsigned char sla, n = 0;
    int rv = 0;
    char twst;

restart:
    if (n++ >= TWI_MAX_REP_TIMES)
	return -1;
begin:

    START(); /* send start condition */
    while (!(TWCR & (1<<TWINT))) ; /* wait for transmission */
    switch ((twst = TWI_STATUS))
    {
	case TWI_REP_START:		/* OK, but should not happen */
	case TWI_START:
	    break;

	case TWI_MT_ARB_LOST:
	    goto begin;

	default:
	    return -1;		/* error: not in start condition */
	    /* NB: do /not/ send stop condition */
    }

    /* send SLA+W */
    SEND(address);
    while (!(TWCR & (1<<TWINT))) ; /* wait for transmission */
    switch ((twst = TWI_STATUS))
    {
	case TWI_MT_SLA_ACK:
	    break;

	case TWI_MT_SLA_NACK:	/* nack during select: device busy writing */
	    goto restart;

	case TWI_MT_ARB_LOST:	/* re-arbitrate */
	    goto begin;

	default:
	    goto error;		/* must send stop condition */
    }

    SEND(ch);
    while (!(TWCR & (1<<TWINT))) ; /* wait for transmission */
    switch ((twst = TWI_STATUS))
    {
	case TWI_MT_DATA_ACK:
	    break;

	case TWI_MT_DATA_NACK:
	    goto quit;

	case TWI_MT_ARB_LOST:
	    goto begin;

	default:
	    goto error;		/* must send stop condition */
    }

quit:
    STOP();

    return rv;

error:
    rv = -1;
    goto quit;

}

unsigned char TWI_SendTo(unsigned char address, char* data)
{
    unsigned char sla, n = 0;
    int rv = 0, len;
    char twst;

    len = strlen(data);

restart:
    if (n++ >= TWI_MAX_REP_TIMES)
	return -1;
begin:

    /* Note [15] */
    START();
    while (!(TWCR & (1<<TWINT))) ; /* wait for transmission */
    switch ((twst = TWI_STATUS))
    {
	case TWI_REP_START:		/* OK, but should not happen */
	case TWI_START:
	    break;

	case TWI_MT_ARB_LOST:
	    goto begin;

	default:
	    return -1;		/* error: not in start condition */
	    /* NB: do /not/ send stop condition */
    }

    /* send SLA+W */
    SEND(address);
    while (!(TWCR & (1<<TWINT))) ; /* wait for transmission */
    switch ((twst = TWI_STATUS))
    {
	case TWI_MT_SLA_ACK:
	    break;

	case TWI_MT_SLA_NACK:	/* nack during select: device busy writing */
	    goto restart;

	case TWI_MT_ARB_LOST:	/* re-arbitrate */
	    goto begin;

	default:
	    goto error;		/* must send stop condition */
    }

    for (; len > 0; len--)
    {
	SEND(*data++);
	while (!(TWCR & (1<<TWINT))) ; /* wait for transmission */
	switch ((twst = TWI_STATUS))
	{
	    case TWI_MT_DATA_NACK:
		goto error;		/* device write protected -- Note [16] */

	    case TWI_MT_DATA_ACK:
		rv++;
		break;

	    default:
		goto error;
	}
    }
quit:
    STOP();

    return rv;

error:
    rv = -1;
    goto quit;
}

